#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstring>
using namespace std;

void showPending()
{
    printf("进程%d的pending表: ", getpid());
    sigset_t set;
    sigemptyset(&set);
    // 查看pending
    sigpending(&set);
    for (int i = 31; i >= 1; i--)
    {
        if (sigismember(&set, i))
            cout << "1";
        else
            cout << "0";
    }
    cout << endl;
}

void handler(int signo)
{
    printf("handler is running... signo: %d\n", signo);

    // 此时向进程发送2~5号信号，观察现象
    int cnt = 20;
    while (cnt--)
    {
        showPending();
        sleep(1);
    }
}

/* sigset_t */

int main()
{
    // signal(SIGINT, handler);
    // signal(SIGQUIT, handler);

    // sigset_t set, oset;
    // sigemptyset(&set);
    // sigaddset(&set, SIGINT);
    // sigaddset(&set, SIGQUIT);

    // // 设置block
    // sigprocmask(SIG_SETMASK, &set, &oset);

    // int cnt = 0;
    // while (true)
    // {
    //     // cout << "pid: " << getpid() << " 正常运行中，暂未收到信号..." << endl;
    //     if (cnt++ == 10)
    //     {
    //         // 解除2、3号信号的阻塞
    //         sigprocmask(SIG_UNBLOCK, &set, &oset);
    //     }
    //     sigset_t set;
    //     sigemptyset(&set);

    //     // 查看pending
    //     sigpending(&set);
    //     showPending(&set);

    //     sleep(1);
    // }

    // signal(SIGFPE, handler);
    // int n = 10;
    // n /= 0;

    // cout << "div zero error..." << endl;

    // int* p = nullptr;
    // *p = 100;

    // signal(SIGINT, handler);
    // signal(SIGQUIT, handler);

    // 阻塞2号信号
    sigset_t set, oset;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigprocmask(SIG_SETMASK, &set, &oset);

    // 绑定2号信号的处理方法为handler
    struct sigaction act, oldact;
    memset(&act, 0, sizeof(act));
    act.sa_handler = handler;
    act.sa_flags = 0;
    // 并设置2号信号处理的同时，阻塞3、4、5号信号
    sigaddset(&act.sa_mask, 3);
    sigaddset(&act.sa_mask, 4);
    sigaddset(&act.sa_mask, 5);
    sigaction(2, &act, &oldact);

    int cnt = 5;
    while (true)
    {
        if (cnt-- == 0)
        {
            // 解除对2号信号的阻塞
            sigprocmask(SIG_SETMASK, &oset, &set);
        }
        showPending();

        sleep(1);
    }

    return 0;
}